
#ifndef _BIT_H_
#define _BIT_H_

#include <stdint.h>

#define Bit_makeSetMask(bit_num) (1 << (bit_num))
#define Bit_makeClearMask(bit_num) (~ Bit_makeSetMask(bit_num))

#define Bit_clear(data, bit_num) ((data) &= Bit_makeClearMask(bit_num))
#define Bit_set(data, bit_num) ((data) |= Bit_makeSetMask(bit_num));
#define Bit_get(data, bit_num) (((uint32_t)(data) >>(bit_num)) & 1u)
#define Bit_test(data, bit_num)	((data & Bit_makeSetMask(bit_num)) != 0 )

#define getByteOffset(BitNum) ((BitNum) >> 3)
#define getBitOffset(BitNum) ((BitNum) & 7)

uint8_t BitBuffer_read(uint8_t BitBuf[], uint32_t BitNum);
void BitBuffer_write(uint8_t BitBuf[], uint32_t BitNum, uint8_t val);
void BitBuffer_copy(uint8_t From[], uint32_t FromPosition, uint8_t To[], uint32_t ToPosition, uint32_t Len);
int32_t BitBuffer_compare(uint8_t BitBuf[], uint32_t Offset, uint8_t Compare[], uint32_t Len);
int32_t BitBuffer_compareBackward(uint8_t BitBuf[], uint32_t Offset, uint8_t Compare[], uint32_t Len);

uint8_t BitBuffer_countSetBitsInByte(uint8_t Byte);
uint32_t BitBuffer_countSetBits(uint8_t BitBuf[], uint32_t len);

typedef struct {
	uint8_t *Buffer;
	uint32_t Size;
	uint32_t Len;
}bit_array_t;

typedef struct {
	bit_array_t *Array;
	uint32_t Offset;
}bit_visitor_t;

void BitArray_initialize(bit_array_t *Array, uint8_t Buf[], uint32_t Size);
uint32_t BitArray_getLength(bit_array_t *Array);
uint32_t BitArray_read(bit_array_t *Array, uint8_t ReadBuf[], uint32_t Offset, uint32_t Len);
uint32_t BitArray_write(bit_array_t *Array, uint8_t WriteBuf[], uint32_t WriteBufOffset, uint32_t Len);
int32_t BitArray_searchForward(bit_array_t *Array, uint32_t Offset,uint8_t BitBuf[], uint32_t Len);
int32_t BitArray_searchBackward(bit_array_t *Array, uint32_t Offset, uint8_t BitBuf[], uint32_t Len);

void BitVisitor_initialize(bit_visitor_t *Visitor, bit_array_t *Array);
uint32_t BitVisitor_getOffset(bit_visitor_t *Visitor);
void BitVisitor_setOffset(bit_visitor_t *Visitor, uint32_t Offset);
int32_t BitVisitor_walkForwardNext(bit_visitor_t *Visitor, uint8_t Window[], uint32_t Size);
int32_t BitVisitor_walkBackwardNext(bit_visitor_t *Visitor, uint8_t Window[], uint32_t Size);

int32_t BitVisitor_searchForwardNext(bit_visitor_t *Visitor, uint8_t SearchBuf[], uint32_t Len);
int32_t BitVisitor_searchBackwardNext(bit_visitor_t *Visitor, uint8_t SearchBuf[], uint32_t Len);
#endif
